EventBridgeスケジューラでRedshift Serverlessのスナップショットを作成するCloudFromationテンプレートを作成してみた
データアナリティクス事業本部のueharaです。
今回は、EventBridgeスケジューラでRedshift Serverlessのスナップショットを作成するCloudFromationテンプレートを作成してみたいと思います。
はじめに
Redshift Serverlessはデフォルトで復旧ポイントが30分ごとに作成されますが、保持期間は24時間となっています。
したがって、例えば「バックアップを7日間保持したい」というケースであれば定期バックアップの仕組みを自前で用意する必要があります。
今回はEventBridgeスケジューラを利用した非常にシンプルな構成で、定期バックアップを設定する方法をご紹介したいと思います。(※Lambda不要)
CloudFormationテンプレートの作成
コード
早速ですが、実行するCloudFormationのテンプレートは以下の通りです。
AWSTemplateFormatVersion: "2010-09-09" Description: "EventBridge Scheduler for snapshot of Redshift Serverless" Parameters: NamespaceName: Type: String SnapshotName: Type: String RetentionPeriod: Type: Number Default: 7 ScheduleSnapTime: Type: String Default: "cron(0 21 * * ? *)" ScheduleTimezone: Type: String Default: Japan Resources: # ------------------------------------------------------------# # EventBridge Scheduler # ------------------------------------------------------------# ScheduleRedShiftServerlessSnap: Type: AWS::Scheduler::Schedule Properties: Name: !Sub '${NamespaceName}-snap-schedule' Description: Redshift Serverless Snapshot ScheduleExpression: !Ref ScheduleSnapTime ScheduleExpressionTimezone: !Ref ScheduleTimezone FlexibleTimeWindow: Mode: "OFF" State: ENABLED Target: Arn: arn:aws:scheduler:::aws-sdk:redshiftserverless:createSnapshot Input: !Sub |- { "NamespaceName": "${NamespaceName}", "RetentionPeriod": ${RetentionPeriod}, "SnapshotName": "${SnapshotName}-<aws.scheduler.execution-id>" } RoleArn: Fn::GetAtt: - SchedulerRedshiftServerlessSnapRole - Arn # ------------------------------------------------------------# # IAM Role # ------------------------------------------------------------# SchedulerRedshiftServerlessSnapRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${NamespaceName}-snap-role" AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - scheduler.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: redshift-serverless-snap PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "redshift-serverless:ConvertRecoveryPointToSnapshot" - "redshift-serverless:CreateSnapshot" - "redshift-serverless:DeleteSnapshot" - "redshift-serverless:GetSnapshot" - "redshift-serverless:ListSnapshots" - "redshift-serverless:UpdateSnapshot" Resource: - "*"
パラメーターについて
スタック作成時に設定するパラメーターは以下の通りです。
パラメーター | 設定値 |
---|---|
NamespaceName | スナップショットを作成したいRedshift Serverlessの名前空間(Namespace)を設定 |
SnapshotName | 作成するスナップショットの名前を設定 |
RetentionPeriod | スナップショットを保持する期間(日)を設定 |
ScheduleSnapTime | スナップショットを作成するタイミングをcron形式で設定 |
ScheduleTimezone | スケジュールする時間のTimezoneを設定 |
デフォルト値としてテンプレートに記載しているRetentionPeriod
が7
で、ScheduleSnapTime
が"cron(0 21 * * ? *)"
であれば、毎晩21時に7日間保持するスナップショットを作成するという挙動になります。
動作確認
CloudFormation実行すると、EventBridgeとその実行ロールの2つのリソースが作成されます。
指定時間になると、設定した保持期間でしっかりスナップショットが作成されていることを確認できました。
ハマったところ
Targetの設定について
Redshift ServerlessのユニバーサルターゲットのService integration ARNは、こちらのページに記載の通り arn:aws:scheduler:::aws-sdk:redshiftserverless:[apiAction]
となっています。
Redshift Serverlessでスナップショットを作成するAPIは CreateSnapshot になるのですが、 arn:aws:scheduler:::aws-sdk:redshiftserverless:CreateSnapshot
をTargetに設定するとCloudFormation実行時に以下のようなエラーが発生します。
Invalid request provided: Invalid RequestJson provided. Reason The api CreateSnapshot is not valid for the service aws-sdk:redshiftserverless. (Service: Scheduler, Status Code: 400, Request ID: xxx)
どうやら、実行するAPIは CreateSnapshot
ですが、 createSnapshot
と頭文字を小文字で指定する必要があるようです。
スナップショット名について
CreateSnapshotでスナップショットを作成する際に、既に同名のスナップショットがある場合は ConflictException
が発生します。
EventBridgeとRedshift Serverlessの間にLamndaを挟んでいればスナップショット名をLamnda内で任意に設定してAPIに渡すことができるのですが、今回はLamndaを利用しない構成にしているので、スナップショット名を一意にするために以下のように設定しています。
${SnapshotName}-<aws.scheduler.execution-id>
aws.scheduler.execution-id
はEventBridge Schedulerで利用てきるコンテキスト属性で、EventBridge SchedulerがTargetの起動の際に割り当てる一意のIDになります。
これにより、スナップショット名は ${SnapshotName}-3f64b7b8-5898-4fbc-b239-abe5f3f4eab9
のような形となり、一意にすることができます。
※参考
最後に
今回は、EventBridgeスケジューラでRedshift Serverlessのスナップショットを作成するCloudFromationテンプレートを作成してみました。
参考になりましたら幸いです。